<template>
  <voice-wave v-if="state.siri" :text="asrText" />
  <transition name="expand">
    <div v-if="show" class="question-and-answers w-[582px] h-[50px] relative flex flex-nowrap overflow-hidden"
      :class="$attrs.class">
      <div class="relative h-full flex-1">
        <template v-if="asrType === 'text'">
          <div v-if="!state.focus" class="text-mode h-full w-full relative flc" @click="handStart">
            请输入您想问的问题
          </div>
          <input v-else ref="asrInput" v-model="resultText" type="text"
            class="text-mode w-full h-full text-center outline-none bg-transparent px-18px" @blur="handEnd"
            @keydown.enter="onChart" />
        </template>
        <template v-else>
          <div v-if="!state.speak" class="text-mode h-full w-full relative flc" @click="handStart">
            <svg-icon name="wave" class="w-[18px] h-[18px] mr-1" />
            点击说话
          </div>
          <div v-else class="finish-speek w-full h-full relative flc select-none" @click="handEnd">
            <span class="relative z-1">{{ getTime }} 点击结束说话</span>
            <div class="progress h-full absolute z-0 top-0 left-0" :style="{ width: `${timeValue / 20 * 100}%` }">
            </div>
          </div>
        </template>
      </div>
      <!-- <div
        v-if="isShowTool"
        class="rigth-tool flc"
      >
        <svg-icon
          :name="asrType === 'text' ? 'voice' : 'text'"
          class="tool-icon"
          color="transparent"
          @click="onHandAsr"
        />
      </div> -->
    </div>
  </transition>
</template>
<script lang="ts" name="QuestionAndAnswersBar" setup>
import { useTost } from '@/utils/comps'
import { useTtsaStore } from '@/store/ttsa'
import { MODE } from '@/constants/ttsa'
import XmovASR from 'xmov-asr-sdk';

const emit = defineEmits(['change-qa-type']);
const show = ref(false);
const ttsa = useTtsaStore();
const partial = ref('');
const resultText = ref('');
const asrInput = ref(null);
const state = reactive({
  focus: false,
  speak: false,
  siri: false
});
const asrType = ref('text');// 语音/文本
const timeValue = ref(0);// 进度动画
const asrSessionId = ref();// 语音识别session id
let loopTimer = null
let asrService = null;

const default_config = {
  origin: import.meta.env.XMOV_APP_XASR_ORIGIN,
  app_id: import.meta.env.XMOV_APP_XASR_APPID,
  secret_key: import.meta.env.XMOV_APP_XASR_SECRET_KEY,
  hotword_list: [],
};

const asrClient = (config) => {
  const asr = new XmovASR({
    origin: config.origin,
    app_id: config.app_id,
    secret_key: config.secret_key,
    hotword_list: config.hotword_list
  })
  return asr;
}

const isShowTool = computed(() => asrType.value === 'text' || state.speak === false);
const asrText = computed(() => resultText.value + partial.value);
const initAsrService = () => {
  asrService = asrClient(default_config);
  asrService.onSocketOpen = () => {
    console.log('连接已建立');
  }
  asrService.onRecStart = (res) => {
    console.log('开始识别', res);
  }
  asrService.onSentenceChange = (res) => {
    console.log('当前这句话部分结果', res);
    partial.value = res?.sentence;
    asrCheck();
  }
  asrService.onSentenceEnd = (res) => {
    resultText.value += res?.sentence;
    partial.value = '';
    console.log('一句话识别完毕', res, resultText.value);
    if (res.session_id) {
      asrSessionId.value = res.session_id;
    }
    asrCheck();
  }
  asrService.onRecComplete = (res) => {
    console.log('识别结束', res);
    onChart()
  }
  asrService.onError = (err) => {
    console.log('识别出错', err);
    useTost(err?.message);
  }
}

const onHandAsr = () => {
  asrType.value = asrType.value === 'text' ? 'asr' : 'text';
}

watch(asrType, () => {
  state.speak = false;
  state.siri = false;
  // if (asrType.value === 'text' && asrService?.state !== 'unready') {
  //   asrService.stop();
  // }
})

// 语音识别开始
const start = () => {
  state.siri = true;
  asrService.start()
    .then(() => {
      resultText.value = '';
      asrSessionId.value = '';
      partial.value = '';
    })
    .catch((error) => {
      console.log('服务异常信息', error);
    });
};

const onChart = async () => {
  if (!asrText.value) return
  try {
    if (asrType.value === 'text') {
      state.focus = false;
    }
    await ttsa.chat(asrText.value, { asr_sessionid: asrSessionId.value });
    resultText.value = '';
    asrSessionId.value = '';
  } catch (error) {
    console.log('识别服务异常信息', error);
  }
  finally {
    resultText.value = '';
  }
}

const stop = () => {
  state.speak = false;
  state.siri = false;
  asrService.stop();
  // if (asrText.value) {
  //   onChart();
  // }
};

const asrCheck = () => {
  if (asrText.value.length > 60) {
    handEnd()
    // stop();
  };
};

const handEnd = () => {
  if (asrType.value === 'text') {
    // input隐藏
    resultText.value = '';
    asrSessionId.value = '';
    state.focus = false;
  } else {
    stop();
    emit('change-qa-type', false);
  }
}

const setLoop = () => {
  removeLoop();
  timeValue.value = 0;
  loopTimer = setInterval(() => {
    timeValue.value++;
    if (timeValue.value >= 20) {
      removeLoop();
      handEnd();
    }
  }, 1000);
}

const removeLoop = () => {
  if (loopTimer) {
    clearInterval(loopTimer);
    loopTimer = null;
  }
}

const getTime = computed(() => {
  const t = timeValue.value;
  const m = Math.trunc(t / 20), s = t % 20;
  return `${m}:${s >= 10 ? s : '0' + s}`;
})

const handStart = async () => {
  if (ttsa.mode !== MODE.QA) return;
  if (asrType.value === 'text') {
    // input显示并聚焦
    state.focus = true;
    nextTick(() => {
      asrInput.value.focus();
    })
  } else {
    if (ttsa.voiceLoading) {
      await ttsa.pause();
    }
    state.speak = true;
    start();
    setLoop();
    emit('change-qa-type', true);
  }
};

onBeforeMount(() => {
  initAsrService();
});

onMounted(() => {
  show.value = true;
})

onUnmounted(() => {
  show.value = false;
})

onBeforeUnmount(() => {
  if (asrService.state !== 'unready') {
    stop();
    asrService.destroy();
  }
});

defineExpose({
  asrType
})
</script>
<style lang="scss" scoped>
@keyframes content {
  from {
    transform: scaleX(0);
    opacity: 0;
  }

  to {
    transform: scaleX(1);
    opacity: 1;
  }
}

.question-and-answers {
  $t: 0.3s;
  @apply backdrop-filter backdrop-blur-2px;
  margin: 0 auto;
  margin-top: 4px;
  background: rgba(23, 54, 96, 0.3);
  border-radius: 29px;
  border: 1px solid rgba(109, 149, 255, 1);
  backdrop-filter: blur(2px);
  transform: translateZ(0);
  animation: content $t linear calc($t / 2) both;

  .text-mode {
    font-size: 16px;
    font-weight: 400;
    color: #FFFFFF;
    line-height: 22px;
    letter-spacing: 1px;
    text-shadow: 1px 1px 0px rgba(33, 73, 115, 0.24);
    caret-color: #EFFEFE;
    cursor: pointer;
  }

  .finish-speek {
    font-size: 16px;
    font-weight: 600;
    color: #FFFFFF;
    line-height: 22px;
    letter-spacing: 1px;
    text-shadow: 1px 1px 5px rgba(33, 73, 115, 0.4);
    cursor: pointer;

    .progress {
      background: rgba(23, 54, 96, 0.6);
      border-radius: 29px 0px 0px 29px;
      backdrop-filter: blur(2px);
      transition: all 0.3s linear;
    }
  }

  .rigth-tool {
    position: relative;
    width: 55px;
    margin-right: 5px;
    cursor: pointer;

    &::before {
      content: '';
      position: absolute;
      top: 50%;
      left: 0;
      width: 2px;
      height: 30px;
      transform: translateY(-50%);
      background: #A2B0DA;
      border-radius: 2px;
    }

    .tool-icon {
      width: 30px;
      height: 30px;
      margin-left: -6px;
    }
  }
}

.expand-enter-active {
  transform: scale(1);
  transition: all 1s ease-out;
}

.expand-leave-active {
  transform: scale(1);
  transition: all 1s ease-out;
}

.expand-enter-from,
.expand-leave-to {
  transform: scale(0);
  opacity: 0;
}
</style>
